#include <iostream>
#include <vector>
#include <cmath>
#include <memory>
#include <execution>
#include <algorithm>
#include "mltree/entities/entries.hpp"

namespace MetricSpaceBenchmark::MLIndex::MLTree {

    template<typename T>
    class MTreeInternal : public MLTreeNode<T> {
    public:
        std::vector<RoutingObject<T>> entries;
        Point<T> center;
        DIS_TYPE radius{};

        MTreeInternal() = default;

        explicit MTreeInternal(std::vector<RoutingObject<T>> objs) : entries(std::move(objs)) {}

        bool operator==(const MTreeInternal<T> &other) const {
            return entries == other.routeObjects && center == other.center && radius == other.radius;
        }

        // 显式定义拷贝构造函数
        MTreeInternal(const MTreeInternal<T> &other) : center(other.center), radius(other.radius) {
            entries.reserve(other.entries.size());
            for (const auto &obj: other.entries) {
                entries.emplace_back(obj.point, obj.cover_radius, obj.subtree ? obj.subtree->clone() : nullptr
                );
            }
        }

        MTreeInternal<T> &operator=(const MTreeInternal<T> &) = default;

        MTreeInternal(MTreeInternal &&) noexcept = default;

        MTreeInternal &operator=(MTreeInternal &&) noexcept = default;

        [[nodiscard]] DIS_TYPE area() const override {
            return M_PI * radius * radius;
        }

        void updateCenterAndRadius() override {
            if (!entries.empty()) {
                center = entries.back().point;
                radius = 0;
                for (auto &entry: entries) {
                    DIS_TYPE dist = center.distance(entry.point);
                    entry.point.dis = dist;
                    if (dist > radius) {
                        radius = dist;
                    }
                }
            }
        }

        std::unique_ptr<MLTreeNode<T>> clone() const override {
            return std::make_unique<MTreeInternal<T>>(*this);
        }

        void rangeQuery(const Point<T> &queryPoint, DIS_TYPE queryRadius, std::vector<Point<T>> &result) override {
            const DIS_TYPE distToCenter = queryPoint.distance(center);

            // 快速剪枝
            if (distToCenter > radius + queryRadius) return;

            // 精确剪枝（三角不等式优化）
            for (const auto &obj: entries) {
                const DIS_TYPE d_QC = queryPoint.distance(obj.point);

                if (d_QC <= queryRadius + obj.cover_radius) {  // 覆盖区域有交集
                    if (obj.subtree) {
                        obj.subtree->rangeQuery(queryPoint, queryRadius, result);
                    }
                }
            }
        }

        void printNode(size_t &count) const override {
            std::cout << "Internal Node:" << std::endl;
            std::cout << "Center OID: " << center.oId << ",覆盖半径: " << radius << ",所涵盖数据量: " << entries.size()
                      << std::endl;

            for (const auto &entry: entries) {
                if (entry.subtree) {
                    entry.subtree->printNode(count);
                }
            }
        }

        [[nodiscard]] bool isLeaf() const override {
            return false;
        }

        [[nodiscard]] std::unordered_set<Point<T>, PointHash<T>, PointEqual<T>> getPoints() const override {
            std::unordered_set<Point<T>, PointHash<T>, PointEqual<T>> nodePoints;
            for (const auto &entry: entries) {
                nodePoints.insert(entry.point);
            }
            return nodePoints;
        }

        bool addEntryIfPossible(const Point<T> &entry, unsigned long M) override {
            if (entries.size() >= M) return false;

            entries.emplace_back(entry.oId, entry.keyObject, entry.dis);
            return true;
        }

        [[nodiscard]] Point<T> getCenter() const override {
            return center;
        }

        [[nodiscard]] DIS_TYPE getRadius() const override {
            return radius;
        }

        std::vector<RoutingObject<T>> &getEntries() {
            return entries;
        }
    };

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    template<typename T>
    class MTreeLeaf : public MLTreeNode<T> {
    public:
        std::vector<DBEntry<T>> entries;
        Point<T> center;
        DIS_TYPE radius{};

        explicit MTreeLeaf(std::vector<DBEntry<T>> objs) : entries(std::move(objs)) {}

        bool operator==(const MTreeLeaf<T> &other) const {
            return entries == other.entries && center == other.center && radius == other.radius;
        }

        MTreeLeaf(const MTreeLeaf<T> &other) : entries(other.entries), center(other.center), radius(other.radius) {}

        MTreeLeaf<T> &operator=(const MTreeLeaf<T> &other) {
            if (this != &other) {
                entries = other.entries;
                center = other.center;
                radius = other.radius;
            }
            return *this;
        }

        MTreeLeaf(MTreeLeaf &&) noexcept = default;

        MTreeLeaf &operator=(MTreeLeaf &&) noexcept = default;

        [[nodiscard]] DIS_TYPE area() const override {
            return M_PI * radius * radius;
        }

        void updateCenterAndRadius() override {
            if (!entries.empty()) {
                center = entries.back().point;
                radius = 0;
                for (auto &entry: entries) {
                    DIS_TYPE dist = center.distance(entry.point);
                    entry.point.dis = dist;
                    if (dist > radius) {
                        radius = dist;
                    }
                }
            }
        }

        std::unique_ptr<MLTreeNode<T>> clone() const override {
            return std::make_unique<MTreeLeaf<T>>(*this);
        }

        void rangeQuery(const Point<T> &queryPoint, DIS_TYPE queryRadius, std::vector<Point<T>> &result) override {
            const DIS_TYPE distToCenter = queryPoint.distance(center);
            if (distToCenter > radius + queryRadius) return;

            // 预筛选（利用覆盖半径）
            const DIS_TYPE minPossibleDist = std::abs(distToCenter - radius);
            if (minPossibleDist > queryRadius) return;

            // 精确检查
            for (const auto &entry: entries) {
                if (queryPoint.distance(entry.point) <= queryRadius) {
                    result.emplace_back(entry.point);
                }
            }
        }

        void printNode(size_t &count) const override {
//            std::cout << "Leaf Node:" << "  Center OID: " << center.oId << ", 覆盖半径: " << radius << ", 所涵盖数据量: "
//                      << entries.size() << std::endl;

            count += entries.size();
        }

        [[nodiscard]] bool isLeaf() const override {
            return true;
        }

        [[nodiscard]] std::unordered_set<Point<T>, PointHash<T>, PointEqual<T>> getPoints() const override {
            std::unordered_set<Point<T>, PointHash<T>, PointEqual<T>> nodePoints;
            for (const auto &entry: entries) {
                nodePoints.insert(entry.point);
            }
            return nodePoints;
        }

        bool addEntryIfPossible(const Point<T> &entry, unsigned long M) override {
            if (entries.size() >= M) return false;

            entries.emplace_back(entry.oId, entry.keyObject, entry.dis);
            return true;
        }

        [[nodiscard]] Point<T> getCenter() const override {
            return center;
        }

        [[nodiscard]] DIS_TYPE getRadius() const override {
            return radius;
        }
    };

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
}